/**
 * Created by zhourh on 2018/9/6.
 *
 * 在 N * N 的网格中，我们放置了一些与 x，y，z 三轴对齐的 1 * 1 * 1 立方体。

 每个值 v = grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。

 现在，我们查看这些立方体在 xy、yz 和 zx 平面上的投影。

 投影就像影子，将三维形体映射到一个二维平面上。

 在这里，从顶部、前面和侧面看立方体时，我们会看到“影子”。

 返回所有三个投影的总面积。



 示例 1：

 输入：[[2]]
 输出：5
 示例 2：

 输入：[[1,2],[3,4]]
 输出：17
 解释：
 这里有该形体在三个轴对齐平面上的三个投影(“阴影部分”)。

 示例 3：

 输入：[[1,0],[0,2]]
 输出：8
 示例 4：

 输入：[[1,1,1],[1,0,1],[1,1,1]]
 输出：14
 示例 5：

 输入：[[2,2,2],[2,1,2],[2,2,2]]
 输出：21
 */
public class ProjectionArea3DShapes {

    public static void main(String[] args) {
        int[][] grid = new int[][]{{2}};
        System.out.println(new ProjectionArea3DShapes().projectionArea(grid));

        int[][] grid2 = new int[][]{{1, 2}, {3, 4}};
        System.out.println(new ProjectionArea3DShapes().projectionArea(grid2));

        int[][] grid3 = new int[][]{{1, 0}, {0, 2}};
        System.out.println(new ProjectionArea3DShapes().projectionArea(grid3));

        int[][] grid4 = new int[][]{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}};
        System.out.println(new ProjectionArea3DShapes().projectionArea(grid4));

        int[][] grid5 = new int[][]{{2, 2, 2}, {2, 2, 2}, {2, 2, 2}};
        System.out.println(new ProjectionArea3DShapes().projectionArea(grid5));
    }

    public int projectionArea(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }

        int xyArea = 0;
        int xzArea = 0;
        int yzArea = 0;

        int height = grid.length;
        int width = grid[0].length;
        int[] maxColumnValues = new int[width];
        for (int row = 0; row < height; row++) {
            int maxRowValue = 0;
            for (int column = 0; column < width; column++) {
                int value = grid[row][column];
                if (value > 0) {
                    xyArea++;
                }

                if (value > maxRowValue) {
                    maxRowValue = value;
                }

                if (value > maxColumnValues[column]) {
                    maxColumnValues[column] = value;
                }
            }

            xzArea += maxRowValue;
        }

        for (int column = 0; column < maxColumnValues.length; column++) {
            yzArea += maxColumnValues[column];
        }

        return xyArea + xzArea + yzArea;
    }
}
